package sk.ygor.raynor.rebind.serializable

import com.google.gwt.core.ext.typeinfo.{JType}
import sk.ygor.raynor.client.json.JSONSerializationException
import sk.ygor.raynor.rebind.common.GeneratorUtils

object JSONSerializableAnalysis extends TypeAnalysis {
  def runAnalysis(serializableType: JType): AnalysisResult = {
    val chain = List(ForbiddenTypeAnalysis, BaseTypeAnalysis, CollectionTypeAnalysis, GenericTypeAnalysis)
    var rejections = List[String]()
    for (a <- chain) {
      a.runAnalysis(serializableType) match {
        case x@Analyzed(structureInfo) => return x
        case Rejected(msg) => rejections = msg :: rejections
      }
    }
    Rejected(rejections.reverse.mkString(" +++ "))
  }

  def getStructureInfo(serializableType: JType) = runAnalysis(serializableType) match {
    case Analyzed(structureInfo) => structureInfo
    case Rejected(msg) => throw new JSONSerializationException(msg)
  }


}

trait TypeAnalysis extends AnyRef with GeneratorUtils {
  def runAnalysis(serializableType: JType): AnalysisResult
}

abstract class AnalysisResult
case class Analyzed(info: StructureInfo) extends AnalysisResult
case class Rejected(reason: String) extends AnalysisResult

case class ClassInfo(packageName: String, simpleName: String) {
  def fullName = packageName + "." + simpleName
}

abstract class StructureInfo {
  def serializer: ClassInfo

  def dependendTypes: List[JType]
}
